home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / posterize.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-29  |  9.4 KB  |  417 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <glib.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "drawable.h"
  27. #include "gdisplay.h"
  28. #include "image_map.h"
  29. #include "posterize.h"
  30. #include "gimplut.h"
  31. #include "gimpui.h"
  32. #include "lut_funcs.h"
  33.  
  34. #include "libgimp/gimpintl.h"
  35.  
  36.  
  37. /*  the posterize structures  */
  38.  
  39. typedef struct _Posterize Posterize;
  40.  
  41. struct _Posterize
  42. {
  43.   gint x, y;    /*  coords for last mouse click  */
  44. };
  45.  
  46. typedef struct _PosterizeDialog PosterizeDialog;
  47.  
  48. struct _PosterizeDialog
  49. {
  50.   GtkWidget     *shell;
  51.  
  52.   GtkAdjustment *levels_data;
  53.  
  54.   GimpDrawable  *drawable;
  55.   ImageMap       image_map;
  56.  
  57.   gint           levels;
  58.  
  59.   gboolean       preview;
  60.  
  61.   GimpLut       *lut;
  62.  
  63.   glong          conn_id;
  64. };
  65.  
  66. /*  the posterize tool options  */
  67. static ToolOptions *posterize_options = NULL;
  68.  
  69. /* the posterize tool dialog  */
  70. static PosterizeDialog *posterize_dialog = NULL;
  71.  
  72.  
  73. /*  posterize action functions  */
  74. static void   posterize_control (Tool *, ToolAction, gpointer);
  75.  
  76. static PosterizeDialog * posterize_dialog_new (void);
  77.  
  78. static void   posterize_preview                  (PosterizeDialog *);
  79. static void   posterize_reset_callback           (GtkWidget *, gpointer);
  80. static void   posterize_ok_callback              (GtkWidget *, gpointer);
  81. static void   posterize_cancel_callback          (GtkWidget *, gpointer);
  82. static void   posterize_preview_update           (GtkWidget *, gpointer);
  83. static void   posterize_levels_adjustment_update (GtkAdjustment *, gpointer);
  84.  
  85. /*  posterize select action functions  */
  86.  
  87. static void
  88. posterize_control (Tool       *tool,
  89.            ToolAction  action,
  90.            gpointer    gdisp_ptr)
  91. {
  92.   switch (action)
  93.     {
  94.     case PAUSE:
  95.       break;
  96.  
  97.     case RESUME:
  98.       break;
  99.  
  100.     case HALT:
  101.       posterize_dialog_hide ();
  102.       break;
  103.  
  104.     default:
  105.       break;
  106.     }
  107. }
  108.  
  109. Tool *
  110. tools_new_posterize (void)
  111. {
  112.   Tool * tool;
  113.   Posterize * private;
  114.  
  115.   /*  The tool options  */
  116.   if (! posterize_options)
  117.     {
  118.       posterize_options = tool_options_new (_("Posterize"));
  119.       tools_register (POSTERIZE, posterize_options);
  120.     }
  121.  
  122.   tool = tools_new_tool (POSTERIZE);
  123.   private = g_new0 (Posterize, 1);
  124.  
  125.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  126.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  127.  
  128.   tool->private = (void *) private;
  129.  
  130.   tool->control_func = posterize_control;
  131.  
  132.   return tool;
  133. }
  134.  
  135. void
  136. posterize_dialog_hide (void)
  137. {
  138.   if (posterize_dialog)
  139.     posterize_cancel_callback (NULL, (gpointer) posterize_dialog);
  140. }
  141.  
  142. void
  143. tools_free_posterize (Tool *tool)
  144. {
  145.   Posterize * post;
  146.  
  147.   post = (Posterize *) tool->private;
  148.  
  149.   /*  Close the posterize dialog  */
  150.   posterize_dialog_hide ();
  151.  
  152.   g_free (post);
  153. }
  154.  
  155. void
  156. posterize_initialize (GDisplay *gdisp)
  157. {
  158.   if (gimp_image_is_empty (gdisp->gimage))
  159.     {
  160.       g_message (_("The image has no drawables."));
  161.       return;
  162.  
  163.     }
  164.   if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
  165.     {
  166.       g_message (_("Posterize does not operate on indexed drawables."));
  167.       return;
  168.     }
  169.  
  170.   /*  The posterize dialog  */
  171.   if (!posterize_dialog)
  172.     posterize_dialog = posterize_dialog_new ();
  173.   else
  174.     if (!GTK_WIDGET_VISIBLE (posterize_dialog->shell))
  175.       gtk_widget_show (posterize_dialog->shell);
  176.  
  177.   posterize_dialog->levels = 3;
  178.  
  179.   posterize_dialog->drawable = gimage_active_drawable (gdisp->gimage);
  180.   posterize_dialog->image_map =
  181.     image_map_create (gdisp, posterize_dialog->drawable);
  182.  
  183.   gtk_adjustment_set_value (GTK_ADJUSTMENT (posterize_dialog->levels_data), 3);
  184.  
  185.   if (posterize_dialog->preview)
  186.     posterize_preview (posterize_dialog);
  187.  
  188.   /* Merge-related undo release signal */
  189.  
  190.   posterize_dialog->conn_id = 
  191.     gtk_signal_connect (
  192.             GTK_OBJECT (gdisp->gimage), "layer_merge",
  193.             GTK_SIGNAL_FUNC (posterize_cancel_callback),
  194.             posterize_dialog
  195.                );
  196. }
  197.  
  198. /**********************/
  199. /*  Posterize dialog  */
  200. /**********************/
  201.  
  202. static PosterizeDialog *
  203. posterize_dialog_new (void)
  204. {
  205.   PosterizeDialog *pd;
  206.   GtkWidget *vbox;
  207.   GtkWidget *hbox;
  208.   GtkWidget *label;
  209.   GtkWidget *spinbutton;
  210.   GtkWidget *toggle;
  211.   GtkObject *data;
  212.  
  213.   pd = g_new (PosterizeDialog, 1);
  214.   pd->preview = TRUE;
  215.   pd->levels  = 3;
  216.   pd->lut     = gimp_lut_new ();
  217.  
  218.   /*  The shell and main vbox  */
  219.   pd->shell =
  220.     gimp_dialog_new (_("Posterize"), "posterize",
  221.              tools_help_func, NULL,
  222.              GTK_WIN_POS_NONE,
  223.              FALSE, TRUE, FALSE,
  224.  
  225.              _("OK"), posterize_ok_callback,
  226.              pd, NULL, NULL, TRUE, FALSE,
  227.              _("Reset"), posterize_reset_callback,
  228.              pd, NULL, NULL, TRUE, FALSE,
  229.              _("Cancel"), posterize_cancel_callback,
  230.              pd, NULL, NULL, FALSE, TRUE,
  231.  
  232.              NULL);
  233.  
  234.   vbox = gtk_vbox_new (FALSE, 2);
  235.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  236.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (pd->shell)->vbox), vbox);
  237.  
  238.   /*  Horizontal box for levels text widget  */
  239.   hbox = gtk_hbox_new (FALSE, 4);
  240.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  241.  
  242.   label = gtk_label_new (_("Posterize Levels:"));
  243.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  244.   gtk_widget_show (label);
  245.  
  246.   /*  levels spinbutton  */
  247.   data = gtk_adjustment_new (3, 2, 256, 1.0, 10.0, 0.0);
  248.   pd->levels_data = GTK_ADJUSTMENT (data);
  249.  
  250.   spinbutton = gtk_spin_button_new (pd->levels_data, 1.0, 0);
  251.   gtk_widget_set_usize (spinbutton, 75, -1);
  252.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  253.  
  254.   gtk_signal_connect (GTK_OBJECT (pd->levels_data), "value_changed",
  255.               GTK_SIGNAL_FUNC (posterize_levels_adjustment_update),
  256.               pd);
  257.  
  258.   gtk_widget_show (spinbutton);
  259.   gtk_widget_show (hbox);
  260.  
  261.   /*  Horizontal box for preview  */
  262.   hbox = gtk_hbox_new (FALSE, 4);
  263.   gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  264.  
  265.   /*  The preview toggle  */
  266.   toggle = gtk_check_button_new_with_label (_("Preview"));
  267.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pd->preview);
  268.   gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
  269.  
  270.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  271.               GTK_SIGNAL_FUNC (posterize_preview_update),
  272.               pd);
  273.  
  274.   gtk_widget_show (label);
  275.   gtk_widget_show (toggle);
  276.   gtk_widget_show (hbox);
  277.  
  278.   gtk_widget_show (vbox);
  279.   gtk_widget_show (pd->shell);
  280.  
  281.   return pd;
  282. }
  283.  
  284. static void
  285. posterize_preview (PosterizeDialog *pd)
  286. {
  287.   if (!pd->image_map)
  288.     {
  289.       g_warning ("posterize_preview(): No image map");
  290.       return;
  291.     }
  292.  
  293.   active_tool->preserve = TRUE;
  294.   posterize_lut_setup (pd->lut, pd->levels, gimp_drawable_bytes(pd->drawable));
  295.   image_map_apply (pd->image_map,  (ImageMapApplyFunc) gimp_lut_process_2,
  296.            (void *) pd->lut);
  297.   active_tool->preserve = FALSE;
  298. }
  299.  
  300. static void
  301. posterize_reset_callback (GtkWidget *widget,
  302.               gpointer   data)
  303. {
  304.   PosterizeDialog *pd;
  305.  
  306.   pd = (PosterizeDialog *) data;
  307.  
  308.   gtk_adjustment_set_value (GTK_ADJUSTMENT (pd->levels_data), 3);
  309. }
  310.  
  311. static void
  312. posterize_ok_callback (GtkWidget *widget,
  313.                gpointer   data)
  314. {
  315.   PosterizeDialog *pd;
  316.  
  317.   pd = (PosterizeDialog *) data;
  318.  
  319.   gimp_dialog_hide (pd->shell);
  320.  
  321.   active_tool->preserve = TRUE;
  322.  
  323.   if (!pd->preview)
  324.     {
  325.       posterize_lut_setup( pd->lut, pd->levels,
  326.                gimp_drawable_bytes (pd->drawable));
  327.       image_map_apply (pd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  328.                (void *) pd->lut);
  329.     }
  330.  
  331.   if (pd->image_map)
  332.     image_map_commit (pd->image_map);
  333.  
  334.   active_tool->preserve = FALSE;
  335.  
  336.   pd->image_map = NULL;
  337.  
  338.   active_tool->gdisp_ptr = NULL;
  339.   active_tool->drawable = NULL;
  340. }
  341.  
  342. static void
  343. posterize_cancel_callback (GtkWidget *widget,
  344.                gpointer   data)
  345. {
  346.   PosterizeDialog *pd;
  347.  
  348.   pd = (PosterizeDialog *) data;
  349.  
  350.   gimp_dialog_hide (pd->shell);
  351.  
  352.   if (pd->image_map)
  353.     {
  354.       active_tool->preserve = TRUE;
  355.       image_map_abort (pd->image_map);
  356.       active_tool->preserve = FALSE;
  357.  
  358.       pd->image_map = NULL;
  359.       gdisplays_flush ();
  360.     }
  361.  
  362.   if (pd->conn_id != 0)
  363.     {
  364.       gtk_signal_disconnect (
  365.                  GTK_OBJECT (gimp_drawable_gimage (pd->drawable)), 
  366.                  pd->conn_id
  367.                 );
  368.       pd->conn_id = 0;
  369.     }
  370.  
  371.   active_tool->gdisp_ptr = NULL;
  372.   active_tool->drawable = NULL;
  373. }
  374.  
  375. static void
  376. posterize_preview_update (GtkWidget *widget,
  377.               gpointer   data)
  378. {
  379.   PosterizeDialog *pd;
  380.  
  381.   pd = (PosterizeDialog *) data;
  382.  
  383.   if (GTK_TOGGLE_BUTTON (widget)->active)
  384.     {
  385.       pd->preview = TRUE;
  386.       posterize_preview (pd);
  387.     }
  388.   else
  389.     {
  390.       pd->preview = FALSE;
  391.       if (pd->image_map)
  392.     {
  393.       active_tool->preserve = TRUE;
  394.       image_map_clear (pd->image_map);
  395.       active_tool->preserve = FALSE;
  396.       gdisplays_flush ();
  397.     }
  398.     }
  399. }
  400.  
  401. static void
  402. posterize_levels_adjustment_update (GtkAdjustment *adjustment,
  403.                     gpointer       data)
  404. {
  405.   PosterizeDialog *pd;
  406.  
  407.   pd = (PosterizeDialog *) data;
  408.  
  409.   if (pd->levels != adjustment->value)
  410.     {
  411.       pd->levels = adjustment->value;
  412.  
  413.       if (pd->preview)
  414.     posterize_preview (pd);
  415.     }
  416. }
  417.